<template>
    <div class="simulation-container">
      <div ref="canvasContainer" class="canvas-wrapper"></div>
      <div class="controls">
        <button @click="startAnimation">开始仿真</button>
        <button @click="pauseAnimation">暂停</button>
        <button @click="resetAnimation">重置</button>
        <button @click="toggleWireframe">{{ wireframeMode ? '实体模式' : '线框模式' }}</button>
        <button @click="toggleAxes">{{ showAxes ? '隐藏坐标轴' : '显示坐标轴' }}</button>
        <div class="slider-container">
          <label>播放速度: {{ speed }}x</label>
          <input type="range" min="0.1" max="5" step="0.1" v-model="speed" @input="updateSpeed">
        </div>
      </div>
      <div class="stats">
        <div class="stat-item">当前位置: {{ currentPosition.x.toFixed(2) }}, {{ currentPosition.y.toFixed(2) }}, {{ currentPosition.z.toFixed(2) }}</div>
        <div class="stat-item">路径进度: {{ progress }}%</div>
        <div class="stat-item">FPS: {{ fps }}</div>
      </div>
    </div>
  </template>
  
  <script setup lang="ts">
  import { ref, onMounted, onBeforeUnmount } from 'vue';
  import * as THREE from 'three';
  import Stats from 'stats.js';
  import * as TWEEN from "three/examples/jsm/libs/tween.module.js";
  import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
  
  // 类型定义
  interface Position {
    x: number;
    y: number;
    z: number;
  }
  
  // 刀具轨迹模拟数据（实际应用中由后端API提供）
  const generateToolPath = (): Position[] => {
    const path: Position[] = [];
    const radius = 30;
    const height = 50;
    const segments = 200;
  
    // 螺旋下降轨迹
    for (let i = 0; i < segments; i++) {
      const angle = (i / segments) * Math.PI * 8;
      const progress = i / segments;
      path.push({
        x: radius * Math.cos(angle),
        y: height * (1 - progress),
        z: radius * Math.sin(angle)
      });
    }
  
    // 平面加工轨迹
    for (let i = 0; i < 100; i++) {
      const x = -30 + (i % 10) * 6;
      const z = -30 + Math.floor(i / 10) * 6;
      path.push({ x, y: 5, z });
    }
  
    return path;
  };
  
  // 响应式数据
  const canvasContainer = ref<HTMLElement | null>(null);
  const toolPath = ref<Position[]>(generateToolPath());
  const currentPosition = ref<Position>({ x: 0, y: 0, z: 0 });
  const progress = ref(0);
  const fps = ref(0);
  const speed = ref(1);
  const wireframeMode = ref(false);
  const showAxes = ref(true);
  
  // Three.js相关对象
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
  const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
  let controls: OrbitControls;
  let stats: Stats;
  
  // 3D对象
  const tool = new THREE.Group();
  const workpiece = new THREE.Mesh();
  const cuttingEffect = new THREE.Group();
  const pathVisualization = new THREE.Line();
  
  // 动画状态
  let animationFrameId: number | null = null;
  let isPlaying = false;
  let currentIndex = 0;
  
  // 初始化场景
  const initScene = () => {
    if (!canvasContainer.value) return;
    
    // 设置渲染器
    renderer.setSize(canvasContainer.value.clientWidth, canvasContainer.value.clientHeight);
    renderer.setPixelRatio(window.devicePixelRatio);
    canvasContainer.value.appendChild(renderer.domElement);
    
    // 设置相机
    camera.position.set(80, 60, 80);
    camera.lookAt(0, 0, 0);
    
    // 添加光源
    const ambientLight = new THREE.AmbientLight(0x404040);
    scene.add(ambientLight);
    
    const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
    directionalLight.position.set(1, 1, 1);
    scene.add(directionalLight);
    
    // 添加坐标轴
    const axesHelper = new THREE.AxesHelper(50);
    scene.add(axesHelper);
    
    // 初始化控制器
    controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.dampingFactor = 0.05;
    
    // 创建工件
    createWorkpiece();
    
    // 创建刀具
    createTool();
    
    // 创建路径可视化
    createPathVisualization();
    
    // 初始化性能监控
    stats = new Stats();
    stats.showPanel(0); // 0: fps, 1: ms, 2: mb
    canvasContainer.value.appendChild(stats.dom);
    
    // 初始位置
    if (toolPath.value.length > 0) {
      currentPosition.value = { ...toolPath.value[0] };
      updateToolPosition();
    }
  };
  
  // 创建工件
  const createWorkpiece = () => {
    const geometry = new THREE.BoxGeometry(60, 10, 60);
    const material = new THREE.MeshPhongMaterial({ 
      color: 0x4472C4,
      shininess: 30,
      side: THREE.DoubleSide
    });
    
    workpiece.geometry = geometry;
    workpiece.material = material;
    workpiece.position.y = -5;
    scene.add(workpiece);
  };
  
  // 创建刀具
  const createTool = () => {
    // 刀具主体
    const toolGeometry = new THREE.CylinderGeometry(0.5, 2, 15, 16);
    const toolMaterial = new THREE.MeshPhongMaterial({ 
      color: 0xFFD700,
      shininess: 100 
    });
    const toolBody = new THREE.Mesh(toolGeometry, toolMaterial);
    toolBody.rotation.x = Math.PI / 2;
    
    // 刀尖
    const tipGeometry = new THREE.ConeGeometry(1, 5, 16);
    const tipMaterial = new THREE.MeshPhongMaterial({ color: 0xC0C0C0 });
    const toolTip = new THREE.Mesh(tipGeometry, tipMaterial);
    toolTip.position.y = 7.5;
    
    // 刀柄
    const handleGeometry = new THREE.CylinderGeometry(0.8, 0.8, 20, 16);
    const handleMaterial = new THREE.MeshPhongMaterial({ color: 0x808080 });
    const toolHandle = new THREE.Mesh(handleGeometry, handleMaterial);
    toolHandle.position.y = -12.5;
    
    tool.add(toolBody, toolTip, toolHandle);
    tool.position.copy(new THREE.Vector3(
      currentPosition.value.x,
      currentPosition.value.y,
      currentPosition.value.z
    ));
    scene.add(tool);
    
    // 切削效果
    const effectGeometry = new THREE.SphereGeometry(3, 16, 16);
    const effectMaterial = new THREE.MeshBasicMaterial({ 
      color: 0xFF4500,
      transparent: true,
      opacity: 0.7
    });
    const effect = new THREE.Mesh(effectGeometry, effectMaterial);
    cuttingEffect.add(effect);
    scene.add(cuttingEffect);
  };
  
  // 创建路径可视化
  const createPathVisualization = () => {
    const points = toolPath.value.map(p => new THREE.Vector3(p.x, p.y, p.z));
    const geometry = new THREE.BufferGeometry().setFromPoints(points);
    
    const material = new THREE.LineBasicMaterial({
      color: 0x00FF00,
      transparent: true,
      opacity: 0.5
    });
    
    pathVisualization.geometry = geometry;
    pathVisualization.material = material;
    scene.add(pathVisualization);
  };
  
  // 更新刀具位置
  const updateToolPosition = () => {
    tool.position.set(
      currentPosition.value.x,
      currentPosition.value.y,
      currentPosition.value.z
    );
    
    // 切削效果位置（稍微高于工件表面）
    cuttingEffect.position.set(
      currentPosition.value.x,
      currentPosition.value.y - 2,
      currentPosition.value.z
    );
    
    // 更新进度
    progress.value = Math.round((currentIndex / toolPath.value.length) * 100);
  };
  
  // 动画循环
  const animate = () => {
    animationFrameId = requestAnimationFrame(animate);
    
    // 更新性能监控
    stats.begin();
    
    // 更新控制器
    controls.update();
    
    // 更新补间动画
    TWEEN.update();
    
    // 渲染场景
    renderer.render(scene, camera);
    
    // 更新FPS显示
    fps.value = Math.round(stats.fps);
    
    stats.end();
  };
  
  // 开始动画
  const startAnimation = () => {
    if (isPlaying) return;
    isPlaying = true;
    
    if (currentIndex >= toolPath.value.length - 1) {
      currentIndex = 0;
    }
    
    moveToNextPoint();
  };
  
  // 移动到下一个点
  const moveToNextPoint = () => {
    if (!isPlaying || currentIndex >= toolPath.value.length - 1) {
      isPlaying = false;
      return;
    }
    
    const startPoint = toolPath.value[currentIndex];
    const endPoint = toolPath.value[currentIndex + 1];
    
    currentIndex++;
    
    // 使用Tween.js创建平滑动画
    const tween = new TWEEN.Tween(currentPosition.value)
      .to(endPoint, 100 / speed.value)
      .easing(TWEEN.Easing.Quadratic.Out)
      .onUpdate(() => {
        updateToolPosition();
        
        // 当刀具接近工件时，显示切削效果
        if (currentPosition.value.y < 10) {
          cuttingEffect.visible = true;
        } else {
          cuttingEffect.visible = false;
        }
      })
      .onComplete(() => {
        if (isPlaying) {
          moveToNextPoint();
        }
      })
      .start();
  };
  
  // 暂停动画
  const pauseAnimation = () => {
    isPlaying = false;
  };
  
  // 重置动画
  const resetAnimation = () => {
    isPlaying = false;
    currentIndex = 0;
    
    if (toolPath.value.length > 0) {
      currentPosition.value = { ...toolPath.value[0] };
      updateToolPosition();
      progress.value = 0;
    }
    
    TWEEN.removeAll();
  };
  
  // 更新播放速度
  const updateSpeed = () => {
    TWEEN.removeAll();
    if (isPlaying) {
      moveToNextPoint();
    }
  };
  
  // 切换线框模式
  const toggleWireframe = () => {
    wireframeMode.value = !wireframeMode.value;
    
    const traverse = (obj: THREE.Object3D) => {
      if ('material' in obj) {
        const mesh = obj as THREE.Mesh;
        if (Array.isArray(mesh.material)) {
          mesh.material.forEach(mat => {
            mat.wireframe = wireframeMode.value;
          });
        } else {
          mesh.material.wireframe = wireframeMode.value;
        }
      }
      obj.children.forEach(child => traverse(child));
    };
    
    traverse(scene);
  };
  
  // 切换坐标轴显示
  const toggleAxes = () => {
    showAxes.value = !showAxes.value;
    scene.traverse(obj => {
      if (obj instanceof THREE.AxesHelper) {
        obj.visible = showAxes.value;
      }
    });
  };
  
  // 响应窗口大小变化
  const onWindowResize = () => {
    if (!canvasContainer.value) return;
    
    camera.aspect = canvasContainer.value.clientWidth / canvasContainer.value.clientHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(canvasContainer.value.clientWidth, canvasContainer.value.clientHeight);
  };
  
  // 生命周期钩子
  onMounted(() => {
    initScene();
    animate();
    window.addEventListener('resize', onWindowResize);
  });
  
  onBeforeUnmount(() => {
    if (animationFrameId) {
      cancelAnimationFrame(animationFrameId);
    }
    window.removeEventListener('resize', onWindowResize);
    
    if (canvasContainer.value && canvasContainer.value.contains(renderer.domElement)) {
      canvasContainer.value.removeChild(renderer.domElement);
    }
  });
  </script>
  
  <style scoped>
  .simulation-container {
    position: relative;
    width: 100%;
    height: 100vh;
    background: #1a1a2e;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  
  .canvas-wrapper {
    flex: 1;
    position: relative;
  }
  
  .controls {
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 10px;
    padding: 12px 20px;
    background: rgba(0, 0, 0, 0.7);
    border-radius: 8px;
    backdrop-filter: blur(5px);
    z-index: 10;
    border: 1px solid rgba(255, 255, 255, 0.1);
  }
  
  .controls button {
    padding: 8px 16px;
    background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.3s ease;
    font-weight: 500;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  }
  
  .controls button:hover {
    background: linear-gradient(135deg, #2575fc 0%, #6a11cb 100%);
    transform: translateY(-2px);
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
  }
  
  .slider-container {
    display: flex;
    align-items: center;
    gap: 10px;
    color: white;
  }
  
  .slider-container input {
    width: 100px;
  }
  
  .stats {
    position: absolute;
    top: 20px;
    left: 20px;
    background: rgba(0, 0, 0, 0.7);
    padding: 12px 20px;
    border-radius: 8px;
    color: white;
    font-family: monospace;
    z-index: 10;
    border: 1px solid rgba(255, 255, 255, 0.1);
  }
  
  .stat-item {
    margin: 5px 0;
  }
  </style>